<?php

namespace Kunfeng\Dify\Client;

use Kunfeng\Dify\Exception\NetworkException;
use GuzzleHttp\Exception\GuzzleException;

/**
 * 重试处理器
 */
class RetryHandler
{
    private $maxRetries;
    private $retryDelay;
    private $backoffMultiplier;

    public function __construct(
        int $maxRetries = 3,
        int $retryDelay = 1000,
        float $backoffMultiplier = 2.0
    ) {
        $this->maxRetries = $maxRetries;
        $this->retryDelay = $retryDelay;
        $this->backoffMultiplier = $backoffMultiplier;
    }

    /**
     * 执行带重试的请求
     */
    public function executeWithRetry(callable $request, array $context = []): mixed
    {
        $attempt = 0;
        $lastException = null;

        while ($attempt <= $this->maxRetries) {
            try {
                return $request();
            } catch (\GuzzleHttp\Exception\GuzzleException $e) {
                $lastException = $e;
                $networkException = NetworkException::fromGuzzleException($e);

                // 如果不可重试或已达到最大重试次数，直接抛出异常
                if (!$networkException->isRetryable() || $attempt >= $this->maxRetries) {
                    throw $networkException;
                }

                // 等待后重试
                $delay = $this->calculateDelay($attempt);
                usleep($delay * 1000); // 转换为微秒
                $attempt++;
            }
        }

        throw $lastException;
    }

    /**
     * 计算重试延迟时间
     */
    private function calculateDelay(int $attempt): int
    {
        return (int) ($this->retryDelay * pow($this->backoffMultiplier, $attempt));
    }

    /**
     * 创建默认重试处理器
     */
    public static function createDefault(): self
    {
        return new self();
    }

    /**
     * 创建自定义重试处理器
     */
    public static function create(int $maxRetries, int $retryDelay, float $backoffMultiplier = 2.0): self
    {
        return new self($maxRetries, $retryDelay, $backoffMultiplier);
    }
}
